import json
import os
import winreg
import re

from DrissionPage import Chromium
from DrissionPage import ChromiumOptions
from common.settings import 关闭浏览器, 定位文本, 运行端口

class hqwyxx():

    def __init__(self):
        super().__init__()
        self.result = self.get_bilibili_cookie_with_drissionpage()
        if self.result:
            self.cookies = self.result.get("cookies", None)
            self.total_episodes = self.result.get("total_episodes", None)
            self.current_url = self.result.get("current_url", None)

    # 01.获取edge地址
    def get_edge_path(self):
        """查找本机 Edge 浏览器安装路径（基于注册表，符合文档103章「运行路径设置」）"""
        try:
            with winreg.OpenKey(
                    winreg.HKEY_LOCAL_MACHINE,
                    r"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\msedge.exe"
            ) as key:
                edge_path = winreg.QueryValue(key, None)
                print(f"注册表中的 Edge 路径：{edge_path}")
                return edge_path if os.path.exists(edge_path) else None
        except (FileNotFoundError, PermissionError):
            return None

    # 02.获取cookie
    def get_bilibili_cookie_with_drissionpage(self, save_path="bilibili_cookies.json", debug_port=运行端口):
        """
        读取已打开浏览器的 B 站 Cookie
        :param debug_port: 已打开浏览器的调试端口（需提前配置，文档102章「手动打开再接管」）
        """
        try:
            # 1. 关键前提：手动配置已打开的 Edge 启用调试端口（文档102章「接管手动打开的浏览器」）
            print(f"📌 重要提示：请确保已按以下步骤配置浏览器：")
            print(f"  1. 右键 Edge 图标 → 属性 → 目标路径后添加：--remote-debugging-port={debug_port}")
            print(f"  2. 启动 Edge 并登录 B 站（确保登录态有效）")
            print(f"  3. 保持浏览器打开，再运行此脚本\n")

            # 2. 初始化浏览器配置（指定调试端口，接管已打开的浏览器，文档102章「指定端口接管」）
            edge_path = self.get_edge_path()
            co = ChromiumOptions()  # 文档103章「ChromiumOptions 配置类」

            if edge_path:
                print(f"✅ 找到 Edge 路径：{edge_path}")
                co.set_browser_path(edge_path)  # 文档103章「set_browser_path() 方法」

            # 核心：通过端口接管已打开的浏览器（文档102章「接管已打开的浏览器-指定端口」）
            co.set_local_port(debug_port)  # 设置要接管的浏览器调试端口
            co.existing_only(True)  # 文档103章「existing_only() 方法」：仅连接已打开的浏览器，不新建
            print(f"🔍 尝试接管端口 {debug_port} 上已打开的浏览器...")

            # 3. 创建浏览器对象（接管已打开的浏览器，而非新建，文档102章「Chromium 对象初始化」）
            browser = Chromium(addr_or_opts=co)
            browser.set.retry_times(10)  # 文档104章「set.retry_times() 全局重试设置」

            # 4. 获取已打开的 B 站标签页（文档105章「标签页管理-get_tab() 方法」）
            try:
                # 按 URL 筛选已登录的 B 站标签页（精准匹配，避免新建）
                tab = browser.get_tab(url="bilibili.com")
                print(f"✅ 成功找到已打开的 B 站标签页：{tab.url}")
            except Exception:
                # 无已打开的 B 站标签页时，新建并跳转（确保获取 Cookie）
                tab = browser.new_tab(url="https://www.bilibili.com")
                print(f"ℹ️ 新建 B 站标签页，已跳转至：https://www.bilibili.com")
                # 等待页面加载（文档122章「等待-doc_loaded() 方法」）
                tab.wait.doc_loaded(timeout=10)



            # 5. 读取 B 站 Cookie（文档108章「获取网页信息-cookies() 方法」）
            # all_domains=True：读取所有子域名 Cookie（如 .bilibili.com）
            # all_info=True：返回完整 Cookie 字段（name/value/domain/expires）
            all_cookies = tab.cookies(all_domains=True, all_info=True)
            bilibili_cookies = [c for c in all_cookies if "bilibili" in c.get("domain", "")]

            if not bilibili_cookies:
                print("❌ 未找到 B 站 Cookie！请确认：")
                print("  1. 浏览器已登录 B 站（非无痕模式）")
                print("  2. 调试端口配置正确（与浏览器启动参数一致）")
                if 关闭浏览器:
                    browser.quit()
                return None

            # 6. 打印并保存 Cookie
            # print("\n=== 已读取的 B 站 Cookie 列表 ===")
            # for idx, cookie in enumerate(bilibili_cookies, 1):
            #     print(f"{idx}. 名称：{cookie['name']}")
            #     print(f"   值：{cookie['value'][:30]}{'...' if len(cookie['value']) > 30 else ''}")
            #     print(f"   域名：{cookie['domain']}")
            #     print(f"   过期：{cookie.get('expires', '会话 Cookie')}")
            #     print("-" * 50)

            # 保存 Cookie（文档136章「下载文件-路径处理」规范）
            save_dir = os.path.dirname(save_path)
            if save_dir and not os.path.exists(save_dir):
                os.makedirs(save_dir)

            with open(save_path, "w", encoding="utf-8") as f:
                json.dump(bilibili_cookies, f, ensure_ascii=False, indent=2)

            print(f"\n✅ Cookie 保存完成！")
            print(f"路径：{os.path.abspath(save_path)}")
            print(f"数量：{len(bilibili_cookies)} 条")

            # 7. 获取视频选集的集数
            j_ksjs, j_jsjs = self.get_video_episode_numbers(tab)
            if j_ksjs is not None:
                print(f"开始集数：{j_ksjs}, 结束集数:{j_jsjs}")
            else:
                print("❌ 未找到视频选集！")

            # 8. 获取当前网址
            current_url = tab.url
            print(f"当前网址：{current_url}")

            # 9. 关闭连接（不关闭手动打开的浏览器，文档104章「close() 方法」）
            if 关闭浏览器:
                browser.quit()
            return {
                "cookies": bilibili_cookies,
                "total_episodes": j_jsjs,
                "current_url": current_url
            }

        except Exception as e:
            error_msg = str(e).lower()
            print(f"\n❌ 失败：{str(e)}")

            if "no existing browser found" in error_msg:
                print("🔧 原因：未找到端口 {} 上运行的浏览器".format(debug_port))
                print("   解决方案：1. 按提示配置浏览器调试端口 2. 确保浏览器已打开并登录 B 站")

            elif "connection refused" in error_msg:
                print("🔧 原因：浏览器调试端口拒绝连接")
                print("   解决方案：1. 关闭浏览器重新启动（确保端口参数正确）2. 检查防火墙是否拦截")

            return {
                "cookies": None,
                "total_episodes": None,
                "current_url": None
            }


    # 03.获取集数
    def get_video_episode_numbers(self,tab, xpath=''):
        """
        从指定 XPath 中提取视频选集的集数（如 1/199），并分割为开始集数和结束集数
        :param tab: 当前标签页对象
        :param xpath: 目标元素的 XPath
        :return: (start_episode, end_episode) 或 None（如果提取失败）
        """
        try:
            # 获取指定 XPath 元素的文本内容
            try:
                elementa = tab.ele(f'text={定位文本}')
            except:
                print("❌ 未找到  视频选集！")
                return None, None
            element = elementa.next()
            text = element.text
            print(f"提取到的文本内容：{text}")

            # 使用正则表达式提取 1/199 格式的数据
            match = re.search(r"(\d+)/(\d+)", text)
            if match:
                start_episode = int(match.group(1))
                end_episode = int(match.group(2))
                print(f"✅ 提取成功：开始集数: {start_episode}, 结束集数: {end_episode}")
                return start_episode, end_episode
            else:
                print("❌ 未找到集数信息！")
                return None, None
        except Exception as e:
            print(f"❌ 提取集数失败：{str(e)}")
            return None, None




if __name__ == "__main__":
    print("=" * 60)
    print("📌 B 站 Cookie 读取工具（基于 DrissionPage 文档规范）")
    print("📌 核心逻辑：接管已打开的浏览器（需提前配置调试端口）")
    print("=" * 60)
    # 调用函数（默认端口9222，可根据实际配置修改）
    # get_bilibili_cookie_with_drissionpage(debug_port=9222)
    hq = hqwyxx()
    print(hq.cookies)
    print(hq.total_episodes)
    print(hq.current_url)